
// TEMPLATE_RUN_START


static void OB_print(OB_VM *vm, STR_PTR strp)
{
    OB_String *text = ptr2str(vm, strp);
    printf("%s\r\n", text->content);
}
static OB_VM *vm;
static char envInited = 0;

#ifdef IOT_GPIO_H
static void rs_IsrTrigger_1(BothIsr* arg){
    AsyncMessage event_isr = {0};
    event_isr.msg.type = OB_Message_Type_USERMSG;
    event_isr.msg.name = arg->arg;
    event_isr.msg.argType = "Integer";
    event_isr.msg.arg.integer = osKernelGetSysTimerCount();
    event_isr.fsm = arg->fsm;
    UINT32 r = LOS_QueueWriteCopy(rs_queue_id,
                             &event_isr,
                             sizeof(AsyncMessage),
                             0);
    if(r!=LOS_OK){
    	printf("LOS_QueueWriteCopy failed %d\n",r);
    }
    return;
}
static void rs_IsrTrigger_0(BothIsr* arg){
    AsyncMessage event_isr = {0};
    event_isr.msg.type = OB_Message_Type_USERMSG;
    event_isr.msg.name = arg->arg;
    event_isr.msg.argType = "Integer";
    event_isr.msg.arg.integer = osKernelGetSysTimerCount();
    event_isr.fsm = arg->fsm;
    UINT32 r = LOS_QueueWriteCopy(rs_queue_id,
                             &event_isr,
                             sizeof(AsyncMessage),
                             0);
    if(r!=LOS_OK){
    	printf("LOS_QueueWriteCopy failed %d\n",r);
    }
    return;
}
static void rs_IsrTrigger_both(BothIsr* arg){
	IotGpioValue v;
	IoTGpioGetInputVal(arg->id, &v);
    IoTGpioUnregisterIsrFunc(arg->id);
	IoTGpioRegisterIsrFunc( arg->id, IOT_INT_TYPE_EDGE,  v?0:1, rs_IsrTrigger_both, arg);
    AsyncMessage event_isr = {0};
    event_isr.msg.type = OB_Message_Type_USERMSG;
    event_isr.msg.name = arg->arg;
    event_isr.msg.argType = "Integer";
    event_isr.msg.arg.integer = osKernelGetSysTimerCount();
    event_isr.fsm = arg->fsm;
    UINT32 r = LOS_QueueWriteCopy(rs_queue_id,
                             &event_isr,
                             sizeof(AsyncMessage),
                             0);
    if(r!=LOS_OK){
    	printf("LOS_QueueWriteCopy failed %d\n",r);
    }
    return;
}
#endif

STATIC UINT32 rs_io_queue_id;
UINT32 g_ioTaskId;

/* 信号量结构体id */
static UINT32 g_semId;

void OB_FSM_post_message_async(OB_VM* _vm,AsyncMessage* aMessage){
    if(vm!=_vm){
        return;
    }
    LOS_TaskLock();
    UINT32 r = LOS_QueueWriteCopy(rs_queue_id, aMessage, sizeof(AsyncMessage), 0);
    LOS_TaskUnlock();
}
int runAsyncOperation(AsyncOperation* op){
    LOS_TaskLock();
    UINT32 r = LOS_QueueWriteCopy(rs_io_queue_id,
                             op,
                             sizeof(AsyncOperation),
                             0);
    if(r!=LOS_OK){
    	printf("IO LOS_QueueWriteCopy failed %d\n",r);
    }else{
        LOS_SemPost(g_semId);
    }
    LOS_TaskUnlock();
    return r;
}
int IOTask(void){
    printf("IOTask\r\n");
    
    // printf("updateRoarVM\n");
    UINT32 uwRet = LOS_OK;
    // osDelay(1);
    AsyncOperation amsg = {0};
    int r = 0;
    UINT32 len = sizeof(AsyncOperation);
    while(1){
        LOS_SemPend(g_semId, 0xFFFFFFFF);
        do{
            LOS_TaskLock();
            uwRet = LOS_QueueReadCopy(rs_io_queue_id, &amsg, &len, 0);
            LOS_TaskUnlock();
            if(uwRet == LOS_OK){
                handleOneAsyncOperationRequest(&amsg);
            }else if(uwRet != LOS_ERRNO_QUEUE_ISEMPTY){
                printf("IO LOS_QueueReadCopy Error %d\n",uwRet);
            }
        }while(uwRet==LOS_OK);
    }
    return 0;
}
void startIOThread(void){
    
    LOS_TaskLock();
    LOS_BinarySemCreate(0, g_semId);
    LOS_QueueCreate("rs_io_queue", 15*sizeof(AsyncOperation), &rs_io_queue_id,0, sizeof(AsyncOperation));
    TSK_INIT_PARAM_S taskParam1 = {0};

    taskParam1.pfnTaskEntry = (TSK_ENTRY_FUNC)IOTask;
    taskParam1.usTaskPrio = 4;
    taskParam1.pcName = "IO Task";
    taskParam1.uwStackSize = 4096;
    // taskParam1.uwResved = LOS_TASK_ATTR_JOINABLE; /* detach 属性 */
    /* 创建高优先级任务，由于锁任务调度，任务创建成功后不会马上执行 */
    UINT32 ret;
    ret = LOS_TaskCreate(&g_ioTaskId, &taskParam1);
    if (ret != LOS_OK) {
      printf("IO Task create Failed!\n");
    }else{
      printf("IO Task create Success!\r\n");
    }
    LOS_TaskUnlock();
}
static void _initEnv(void)
{
    if (envInited)
    {
        return;
    }
    startIOThread();
	uint8_t  saved[16] = {0};
	uint16_t readedLength;
	errcode_t e = uapi_nv_read(NV_KEY_MAC, 16,&readedLength, saved);
	printf("\r\nreaded %d srand:%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\r\n",
				readedLength,
                (0xFF & saved[0]),
				(0xFF& saved[1]),
				(0xFF& saved[2]),
				(0xFF& saved[3]),
				(0xFF& saved[4]),
				(0xFF& saved[5]),
				(0xFF& saved[6]),
				(0xFF& saved[7]),
				(0xFF& saved[8]),
				(0xFF& saved[9]),
				(0xFF& saved[10]),
				(0xFF& saved[11]),
				(0xFF& saved[12]),
				(0xFF& saved[13]),
				(0xFF& saved[14]),
				(0xFF& saved[15]));
    printf("\r\ninit 1");
    hal_cipher_trng_init();
    printf("\r\ninit 2");
    td_u32 seed = 0;
    hal_cipher_trng_get_random(&seed);
    for(int i = 0; i < 16; i++){
        seed ^= saved[i];
    }
    printf("\r\ninit 3");
    saved[15] = saved[15] ^ (seed & 0xff);
    saved[14] = saved[14] ^ (saved[15] & 0xff);
    printf("\r\ninit 4");
    if(e!=0){
        printf("\r\ninit 4.1");
        uapi_nv_write(NV_KEY_MAC, saved, 16);
        printf("\r\ninit 5");
        uapi_nv_flush();
    }
    printf("\r\ninit 6");
    printf("seed %d\r\n",seed);
    srand(seed);
    printf("\r\ninit 7");
    uapi_nv_init();
    printf("\r\ninit 8");
    // hal_cipher_trng_deinit();
    uapi_gpio_init();
    printf("\r\ninit 9");
    
    // IoTI2cInit(I2C_MASTER_ADDR,I2C_SET_BAUDRATE);
    /* I2C pinmux. */
    errcode_t r = uapi_pin_set_mode(I2C_SCL_MASTER_PIN, I2C_MASTER_PIN_MODE);
	  if(r!=0){
    	  printf("1r:%d",r);
	  }
    r = uapi_pin_set_mode(I2C_SDA_MASTER_PIN, I2C_MASTER_PIN_MODE);
	  if(r!=0){
    	printf("2r:%d",r);
	  }
    r = uapi_i2c_master_init(I2C_MASTER_BUS_ID, I2C_SET_BAUDRATE, I2C_MASTER_ADDR);
	  if(r!=0){
    	printf("3r:%d",r);
	  }
    printf("\r\nI2C init finished.SDA %d,SCL %d,PIN_MODE %d baudrate %d,master_addr %d \r\n",I2C_SDA_MASTER_PIN,I2C_SCL_MASTER_PIN,I2C_MASTER_PIN_MODE, I2C_SET_BAUDRATE, I2C_MASTER_ADDR);

    LOS_QueueCreate("rs_event_queue", 5*sizeof(AsyncMessage), &rs_queue_id,0, sizeof(AsyncMessage));
    
#ifdef HI_ADC_H
    r = uapi_adc_init(ADC_CLOCK_500KHZ);
    if(r!=0){
    	printf("uapi_adc_init failed %d\r\n",r);
    }
    uapi_adc_power_en(AFE_SCAN_MODE_MAX_NUM, true);
    
    for (int i = 0; i < ADC_CHANNEL_MAX_NUM; i++) {
        adc_data[i] = 0;
    }
#endif

#ifdef SERVICE_WIFI_DEVICE_C_H
    if(saved[0]+saved[1]+saved[2]+saved[3]+saved[4]+saved[5] != 0){
        wifi_set_base_mac_addr(saved,6);
        mac_set = 1;
    }else{
        wifi_get_base_mac_addr(saved, 6);
		uapi_nv_write(NV_KEY_MAC, saved, 16);
		uapi_nv_flush();
	    printf("\r\nreaded %d srand:%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\r\n",
				readedLength,
                (0xFF& saved[0]),
				(0xFF& saved[1]),
				(0xFF& saved[2]),
				(0xFF& saved[3]),
				(0xFF& saved[4]),
				(0xFF& saved[5]),
				(0xFF& saved[6]),
				(0xFF& saved[7]),
				(0xFF& saved[8]),
				(0xFF& saved[9]),
				(0xFF& saved[10]),
				(0xFF& saved[11]),
				(0xFF& saved[12]),
				(0xFF& saved[13]),
				(0xFF& saved[14]),
				(0xFF& saved[15]));
    }
    wifi_event_stru wifiEventListener = {
        .wifi_event_connection_changed = OnWifiConnectionChanged,
        .wifi_event_scan_state_changed = OnWifiScanStateChanged,
        // .OnHotspotStateChanged = OnHotspotStateChanged,
        // .OnHotspotStaJoin = OnHotspotStaJoin,
        // .OnHotspotStaLeave = OnHotspotStaLeave
    };
    wifi_register_event_cb(&wifiEventListener);
    wifi_init();
    osDelay(300);
    // struct netif *netif_p = NULL;
    // netif_p = netifapi_netif_find("wlan0");
    // if (netif_p == NULL) {
    // 	printf("netifapi_netif_find NULL\n");
    // }else{
    // err_t ret = netifapi_dhcp_start(netif_p);
    //     if(ret!=0){
    // 	    printf("netifapi_dhcp_start failed %d\n",ret);
    //     }
    // }
#else
#endif

    printf("ROAR init finished.\r\n");
    envInited = 1;
}
int startRoarVM(void)
{
    _initEnv();
    vm = createOBVM(NULL);
    return 0;
}
int updateRoarVM(void)
{
    UINT32 uwRet = LOS_OK;
    // osDelay(1);
    AsyncMessage amsg = {0};
    int r = 0;
    while(uwRet == LOS_OK){
#ifdef NO_SYS
        sys_check_timeouts();
#endif
        UINT32 len = sizeof(AsyncMessage);
        LOS_TaskLock();
        uwRet = LOS_QueueReadCopy(rs_queue_id, &amsg, &len, 0);
        LOS_TaskUnlock();
        if(uwRet == LOS_OK){
            OB_Message* event_isr = OB_malloc(vm, OB_Message, "OB_Message",OB_Message_destroy);
            MSG_PTR msg1 = GetOBPtrByNative(vm, event_isr);
            event_isr->type = amsg.msg.type;
            event_isr->name = amsg.msg.name;
            event_isr->argType = amsg.msg.argType;
            if(strcmp(event_isr->argType,"String")==0){
                event_isr->arg.ptrdiff = str2ptr((char*)vm,amsg.msg.arg.ptrdiff);
            }else{
                event_isr->arg.integer = amsg.msg.arg.integer;
            }
            FSM_PTR fsm = amsg.fsm;
            if(amsg.nativeObj != NULL){
                void* ptr = __OB_malloc(vm, amsg.nativeObjSize, event_isr->type,NULL);
                size_t ob_ptr = GetOBPtrByNative(vm, ptr);
                memcpy_s(ptr,amsg.nativeObjSize,amsg.nativeObj,amsg.nativeObjSize);
                free(amsg.nativeObj);
                OB_link_obj(vm, msg1,offsetof(OB_Message,arg),ob_ptr);
                event_isr->arg.ptrdiff = ob_ptr;
            }
            if(fsm != 0){
                OB_FSM_post_message(vm,fsm,msg1);
            }else{
                OB_broadcastMessage(vm,msg1,event_isr->type);
            }
            r = OB_VM_update(vm);
            // hi_watchdog_feed();
        }else if(uwRet != LOS_ERRNO_QUEUE_ISEMPTY){
            printf("LOS_QueueReadCopy Error %d\n",uwRet);
        }
    }
    r = OB_VM_update(vm);
    return r;
}
// TEMPLATE_RUN_END

static int RoarUpdateTask(void){
  osDelay(200);
  printf("startRoarVM\r\n");
#ifdef NO_SYS
  printf("use sys_check_timeouts();\r\n");
#endif
  startRoarVM();
  while(true){
    usleep(1);
    updateRoarVM();
    // char block[409600] = {0};
    // printf("EMPTY BLOCK 2: %zu",block);
    // char* f = calloc(1,50000);
    // printf("EMPTY BLOCK 1: %zu",f);
    // printf("s %s",f);
    // free(f);
  }
  return 0;
}

static void startRoarUpdate1(void) {

    /* 锁任务调度，防止新创建的任务比本任务高而发生调度 */
    LOS_TaskLock();

    printf("LOS_TaskLock() Success!\r\n");
    TSK_INIT_PARAM_S taskParam1 = {0};
    UINT32 g_taskId;

    taskParam1.pfnTaskEntry = (TSK_ENTRY_FUNC)RoarUpdateTask;
    taskParam1.usTaskPrio = 4;
    taskParam1.pcName = "RoarLang Task";
    taskParam1.uwStackSize = 8192;
    // taskParam1.uwResved = LOS_TASK_ATTR_JOINABLE; /* detach 属性 */
    /* 创建高优先级任务，由于锁任务调度，任务创建成功后不会马上执行 */
    UINT32 ret;
    ret = LOS_TaskCreate(&g_taskId, &taskParam1);
    if (ret != LOS_OK) {
      printf("RoarLang Task create Failed!\n");
    }else{
      printf("RoarLang Task create Success!\r\n");
    }
    LOS_TaskUnlock();

}
static void MainEntry(void) {
  osal_printk("MainEntry\r\n");
  startRoarUpdate1();
  return;
}
app_run(MainEntry);